package com.lf.mykotlin.function

/**
 * @date: 2023/5/12
 */
class MyKotlinSystemFun {

    /*
        kotlin内置函数
            apply 和 also 函数的返回值是该对象本身, let 和 run 函数的返回值是 lambda 表达式的结果。
            1. apply 函数在对象上执行一些操作，并返回该对象本身。它通常用于在对象创建后立即对其进行初始化。
            2. also 函数类似于 apply 函数，但它返回原始对象的引用。它通常用于对对象进行一些副作用，例如打印日志或修改对象状态。
            3. let 函数在 lambda 中对对象进行一些操作，并返回 lambda 表达式的结果。它通常用于在某些条件下对对象进行转换或计算。
            4. run 函数类似于 let 函数，但它返回 lambda 表达式的结果。它通常用于对对象进行计算，并返回计算结果

     */


    /**
     *
        1. apply方式
            使用apply方式时，xxx.apply 在匿名函数体中会持有一个this == xxx本身
            apply内置函数会存在返回值，始终返回xxx本身，就可以一直链式调用
            在apply中this可以省略
     *
     */
    fun testApply() {

        var person = Person().apply {
            name = "zhangsan"
            age = 10
            address = "zhengzhoushi"
        }.apply {
            age ++
        }
    }

    /**
     * 2. let
     *      let内置函数Lambda表达式的会持有一个it == list本身
            并且将Lambda表达式中最后一行作为返回值
     */
    fun testLet() {
        val list : List<Int> = listOf(1,2,3,4,5)
        val result = list.let {
            it.first()+it.first()
        }

        val person = Person()
        val ageAfterFiveYears = person.let {
            it.age + 5
        }
    }


    /**
     * 3. also
     *      also 函数的返回值是接收者对象本身，而 Lambda 表达式的参数是接收者对象，通常用 it 作为隐式名称
     */
    fun testAlso() {
        val person = Person().also {
            it.name = "Bob"
            it.age = 30
        }
    }


    /**
     * 4. run
     *      run 函数在 Lambda 表达式中直接访问接收者对象的属性和方法，同时返回 Lambda 表达式的结果
     */
    fun testRun() {
        val person = Person()
        val greeting = person.run {
            "Hello, $name! You are $age years old."
        }
    }


    /**
     *  5. with
     *      with适用于调用同一个类的多个方法时，可以省去类名重复，直接调用类的方法即可
     *      返回值为 lamda的返回值  即最后一行的结果
     */
    fun testWith() {

        var person = Person()

        val result = with(person, {
            println("name is $name, age is $age , address is $address")
        })

        //或者 由于with函数最后一个参数是一个函数，可以把函数提到圆括号的外部
        val result2 = with(person) {
            println("name is $name, age is $age , address is $address")
        }
    }


    class Person {
        lateinit var name : String
        var age : Int = 0
        lateinit var address:String
    }

}